package com.daikun.common.advice;

import cn.hutool.extra.spring.SpringUtil;
import com.daikun.common.enums.BaseCountryEnum;
import com.daikun.common.enums.BaseResultEnum;
import com.daikun.common.exception.BizException;
import com.daikun.common.iface.I18nMessageIface;
import com.daikun.common.iface.BaseResultIface;
import com.daikun.common.model.BaseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Arrays;
import java.util.stream.Collectors;

/**
 * 全局异常拦截器
 * 若需要对返回的文案进行国际化编码，需要自己实现 {@link I18nMessageIface} 接口，否则返回异常默认的文案描述
 * @author earl created 2025-07-03
 * @version init 0.0.1
 */
@Slf4j
@RestControllerAdvice
public class BaseControllerAdvice {

    @ResponseBody
    @ExceptionHandler(Throwable.class)
    public BaseResult<Object> handleException(Throwable e) {
        BizException bizException = isBizException(e);
        if (bizException != null) {
            // 当前是自定义业务异常
            log.info("BaseControllerAdvice.bizException info -> msg = {}, item = {}", bizException.getMessage(), bizException.getItem());
            return BaseResult.fail(bizException.getItem(), getMessage(bizException.getItem()), bizException.getData());
        }
        if (e instanceof HttpMessageNotReadableException) {
            // post 请求时，如果入参添加了 @RequestBody 的注解，但是调用方没有传参数内容，则会报这个错
            log.info("BaseControllerAdvice.httpMessageNotReadableException info -> 参数不能为空");
            return BaseResult.fail(BaseResultEnum.PARAM_FAIL, getMessage(BaseResultEnum.PARAM_FAIL));
        }
        log.info("BaseControllerAdvice.handleException info -> msg = {}", e.getMessage(), e);
        return BaseResult.fail(BaseResultEnum.SYSTEM_ERROR, getMessage(BaseResultEnum.SYSTEM_ERROR));
    }

    /**
     * 递归判断异常链是否包含指定异常
     * @param e 原始异常
     * @return null 非指定异常，否则返回指定异常对象
     */
    private static BizException isBizException(Throwable e) {
        if (e == null) {
            return null;
        }
        if (e.getCause() instanceof BizException) {
            return (BizException) e.getCause();
        }
        return isBizException(e.getCause());
    }

    /**
     * 获取国际化文案
     * @param item 当前异常信息
     * @return 对应国家的文案
     */
    private static String getMessage(BaseResultIface item) {
        if (item == null) {
            return null;
        }

        // 获取调用者对应的国际化实现类
        I18nMessageIface msgBean = SpringUtil.getBean(I18nMessageIface.class);
        // 若获取不到，则返回异常默认文案
        if (msgBean == null) {
            return item.getMsg();
        }
        // 返回调用者自定义的国际化文案
        return msgBean.getI18nMsg(item.getCode());
    }
}
